#include <memory>
#include <utility>
#include <variant>
#include <vector>

class FrontEndDeveloper {
  public:
    void develop() {developFrontEnd();}
  private:
    void developFrontEnd() {}
};

class BackEndDeveloper {
  public:
    void develop() {developBackEnd();}
  private:
    void developBackEnd() {}
};

class MiddlewareDeveloper {
  public:
    void develop() {developMiddleware();}
  private:
    void developMiddleware() {}
};

template <typename... Devs>
class Project {
  public:
    using Developers = std::vector<std::variant<Devs...>>;

    explicit Project(Developers devs) : developers_(std::move(devs)) {}
    void deliver() {
      for (auto& dev : developers_) {
        std::visit([](auto &d) {
          d.develop();}, dev
        );
      }
    }
  private:
    Developers developers_;
};

using MyProject = Project<FrontEndDeveloper, MiddlewareDeveloper, BackEndDeveloper>;

int main (int argc, char *argv[]) {
  auto alice = FrontEndDeveloper{};
  auto bob = BackEndDeveloper{};
  auto charlie = MiddlewareDeveloper{};

  auto new_project = MyProject{{alice, charlie, bob}};
  new_project.deliver();
  return 0;
}
